package no.uib.hplims.models;

import javax.persistence.Entity;

import no.uib.hplims.models.RuleFactory.FLAG_TYPE;
import no.uib.hplims.models.RuleFactory.POSITION;
import no.uib.hplims.models.RuleFactory.RULE_META;
import no.uib.hplims.models.RuleFactory.RULE_TYPE;

import org.apache.commons.lang.StringUtils;
import org.vaadin.appfoundation.authentication.data.User;
import org.vaadin.appfoundation.persistence.data.AbstractPojo;

@Entity
public class Rule extends AbstractPojo {

	private static final long serialVersionUID = -5795234668412827300L;

	private String ruleName;
	private User creator;

	private FLAG_TYPE flagType;
	private RULE_TYPE ruleType;
	private POSITION position;
	private RULE_META meta;

	private int occurences;
	private int minLength;
	private int maxLength;
	private String aminoAcid;

	public Rule() {

	}

	public String validate(String sequence, int lineNumber) {
		if (ruleType == RULE_TYPE.LENGTH)
			return validateLength(sequence, lineNumber);
		else if (ruleType == RULE_TYPE.ALLOW)
			return validateAllowedAminoAcid(sequence, lineNumber);
		else if (ruleType == RULE_TYPE.DISALLOW)
			return validateDisallowedAminoAcid(sequence, lineNumber);
		return "Something went wrong";
	}

	private String validateLength(String sequence, int lineNumber) {
		if (sequence.length() < minLength) {
			return "Sequence must be minimum "
					+ minLength + " amino acids long.";
		} else if (sequence.length() > maxLength) {
			return "Sequence can be maximim "
					+ maxLength + " amino acids long.";
		}
		return "OK";
	}

	private String validateAllowedAminoAcid(String sequence, int lineNumber) {
		if (position == POSITION.SEQUENCE) {
			if (StringUtils.countMatches(sequence.toUpperCase(), aminoAcid) > occurences) {
				return "Sequence contains more than "
						+ occurences + " " + aminoAcid;
			}
		}
		return "OK";
	}

	private String validateDisallowedAminoAcid(String sequence, int lineNumber) {
		if (position == POSITION.SEQUENCE) {
			if (StringUtils.countMatches(sequence.toUpperCase(), aminoAcid) > occurences) {
				return aminoAcid + " is not allowed in the sequence.";
			}
		} else if (position == POSITION.N_TERMINAL) {
			if (sequence.startsWith(aminoAcid)) {
				return "Sequence can not have "
						+ aminoAcid + " in N-terminal position";
			}
		} else if (position == POSITION.C_TERMINAL) {
			if (sequence.endsWith(aminoAcid)) {
				return "Sequence can not have "
						+ aminoAcid + "in C-terminal position";
			}
		}
		return "OK";
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return ruleName;
	}

	/**
	 * @return the ruleName
	 */
	public String getRuleName() {
		return ruleName;
	}

	/**
	 * @param ruleName
	 *            the ruleName to set
	 */
	public void setRuleName(String ruleName) {
		this.ruleName = ruleName;
	}

	/**
	 * @return the creator
	 */
	public User getCreator() {
		return creator;
	}

	/**
	 * @param creator
	 *            the creator to set
	 */
	public void setCreator(User creator) {
		this.creator = creator;
	}

	/**
	 * @return the flagType
	 */
	public FLAG_TYPE getFlagType() {
		return flagType;
	}

	/**
	 * @param flagType
	 *            the flagType to set
	 */
	public void setFlagType(FLAG_TYPE flagType) {
		this.flagType = flagType;
	}

	/**
	 * @return the ruleType
	 */
	public RULE_TYPE getRuleType() {
		return ruleType;
	}

	/**
	 * @param ruleType
	 *            the ruleType to set
	 */
	public void setRuleType(RULE_TYPE ruleType) {
		this.ruleType = ruleType;
	}

	/**
	 * @return the position
	 */
	public POSITION getPosition() {
		return position;
	}

	/**
	 * @param position
	 *            the position to set
	 */
	public void setPosition(POSITION position) {
		this.position = position;
	}

	/**
	 * @return the meta
	 */
	public RULE_META getMeta() {
		return meta;
	}

	/**
	 * @param meta
	 *            the meta to set
	 */
	public void setMeta(RULE_META meta) {
		this.meta = meta;
	}

	/**
	 * @return the occurences
	 */
	public int getOccurences() {
		return occurences;
	}

	/**
	 * @param occurences
	 *            the occurences to set
	 */
	public void setOccurences(int occurences) {
		this.occurences = occurences;
	}

	/**
	 * @return the minLength
	 */
	public int getMinLength() {
		return minLength;
	}

	/**
	 * @param minLength
	 *            the minLength to set
	 */
	public void setMinLength(int minLength) {
		this.minLength = minLength;
	}

	/**
	 * @return the maxLength
	 */
	public int getMaxLength() {
		return maxLength;
	}

	/**
	 * @param maxLength
	 *            the maxLength to set
	 */
	public void setMaxLength(int maxLength) {
		this.maxLength = maxLength;
	}

	/**
	 * @return the aminoAcid
	 */
	public String getAminoAcid() {
		return aminoAcid;
	}

	/**
	 * @param aminoAcid
	 *            the aminoAcid to set
	 */
	public void setAminoAcid(String aminoAcid) {
		this.aminoAcid = aminoAcid;
	}

}
